#include <task.h>
#include <log.h>
#include <framework.h>
#include <modules.h>
#include <taskManager.h>

Task::Task(const std::string& name, FUNCPTR func, void* arg)
    : m_name(name), m_function(func), m_arg(arg), m_isRunning(false) 
{

}

Task::~Task() 
{
    if (m_threadId.joinable()) 
    {
        m_threadId.join();
    }
    LOG_TRACE("Task destroyed: %s (ID: %u)", m_name.c_str(), getThreadId());
}

Task::TASK_ID Task::getThreadId() const
{
    return m_taskId;
}

const std::string& Task::getName() 
{
    return m_name; 
}

bool Task::isRunning() const
{
    return m_isRunning; 
}
void Task::execute()
{
    TaskPtr taskCopy = shared_from_this();
    m_threadId = std::move(std::thread([taskCopy]() {taskCopy->Run(); }));
    m_taskId = m_threadId.get_id();
    m_threadId.detach();
}

void Task::Run() 
{
    TaskPtr taskCopy = shared_from_this();
    m_isRunning = true;
    GET_FRAMEWORK_MGR->callObjectMethod<TaskManager>(MODULE_TASK_MGR, &TaskManager::addTask, std::move(taskCopy));
    try 
    {
        if (m_function) 
        {
            (void) m_function(m_arg, shared_from_this());
        }
    } 
    catch (const std::exception& e) 
    {
        LOG_ERROR("Task %s (ID: %llu) threw exception: %s",
                 m_name.c_str(), getThreadId(), e.what());
    } 
    catch (...) 
    {
        LOG_ERROR("Task %s (ID: %llu) threw unknown exception",
                 m_name.c_str(), getThreadId());
    }
    m_isRunning = false;
    GET_FRAMEWORK_MGR->callObjectMethod<TaskManager>(MODULE_TASK_MGR, &TaskManager::removeTask, getThreadId());
}